﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace nr.Tombola.Windows.Server
{
    public partial class MainForm : Form
    {
        private nr.Tombola.Net.GameServer Server { get; set; }
        private nr.Tombola.Game Game { get; set; }
        private DateTime LastExtract { get; set; }
        private TimeSpan ExtractTimeSpan
        {
            get { return TimeSpan.FromSeconds((double)txtTimeSpan.Value); }
            set { txtTimeSpan.Value = (int)value.TotalSeconds; }
        }

        public MainForm()
        {
            InitializeComponent();
        }

        private void MainForm_Load(object sender, EventArgs e)
        {
            Server = new Net.GameServer();
            Server.ClientAccepted += Server_ClientAccepted;
            Server.ClientRemoved += Server_ClientRemoved;
            Game = new Game();
            ExtractTimeSpan = TimeSpan.FromSeconds(10);
            txtAddress.Items.Clear();
            txtAddress.Items.Add(System.Net.IPAddress.Parse("127.0.0.1"));
            System.Net.NetworkInformation.IPGlobalProperties properties = System.Net.NetworkInformation.IPGlobalProperties.GetIPGlobalProperties();
            IEnumerable<System.Net.IPAddress> addr = System.Net.Dns.GetHostAddresses(properties.HostName);
            foreach (System.Net.IPAddress a in addr)
                if (a.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork) txtAddress.Items.Add(a);
            txtAddress.SelectedIndex = 0;
            txtPort.Value = 9090;
            UpdateClientsCount(0);
        }

        delegate void UpdateClientsCountDelegate(int clientCount);

        void UpdateClientsCount(int count)
        {
            lblClients.Text = count.ToString();
        }

        void Server_ClientAccepted(object sender, Net.ClientAcceptedEventArgs e)
        {
            this.BeginInvoke(new UpdateClientsCountDelegate(UpdateClientsCount), Server.ConnectedClients);
            if (Game.Running)
                SendGameStatus(e.ClientID);
        }

        private void SendGameStatus(Guid clientID)
        {
            StringBuilder builder = new StringBuilder("1000:STAT:");
            foreach (object item in lbNumbers.Items)
                builder.AppendFormat("{0}|", item);
            --builder.Length;

            Server.SendMessage(clientID, builder.ToString());
        }

        void Server_ClientRemoved(object sender, Net.ClientRemovedEventArgs e)
        {
            this.BeginInvoke(new UpdateClientsCountDelegate(UpdateClientsCount), Server.ConnectedClients);
        }

        private void timer_Tick(object sender, EventArgs e)
        {
            DateTime now = DateTime.Now;
            lblTime.Text = string.Format("Orario del server: {0:T}", now);
            if (Game.Running && now.Subtract(LastExtract) > ExtractTimeSpan)
                EnableExtraction();
        }

        private void EnableExtraction()
        {
            btnExtract.Enabled = true;
            txtManualNumber.Enabled = true;
        }

        private void btnGameStart_Click(object sender, EventArgs e)
        {
            btnGameStart.Enabled = false;
            btnGameStop.Enabled = true;
            btnExtract.Enabled = true;
            btnManuaExtract.Enabled = false;

            Game.Start();
            lblLastNumber.Text = string.Empty;
            lbNumbers.Items.Clear();
            if (Server.Running)
            {
                Server.StartGame();
            }
        }

        private void EndOfGame()
        {
            btnGameStart.Enabled = true;
            btnGameStop.Enabled = false;
            btnExtract.Enabled = false;
            btnManuaExtract.Enabled = false;
            txtManualNumber.Enabled = false;

            Game.Stop();
            if (Server.Running) Server.EndGame();
        }

        private void btnGameStop_Click(object sender, EventArgs e)
        {
            DialogResult answer =
                MessageBox.Show(this,"Sei sicuro di voler terminare la partita in corso?",
                    "[nr.Tombola] Server di Gioco", MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2);
            if (answer == System.Windows.Forms.DialogResult.Yes)
                EndOfGame();
        }

        private void btnSet_Click(object sender, EventArgs e)
        {
            Server.LocalAddress = (System.Net.IPAddress)txtAddress.SelectedItem;
            Server.Port = (int)txtPort.Value;
        }

        private void btnServerStart_Click(object sender, EventArgs e)
        {
            btnServerStart.Enabled = false;
            visualServerStatus.Flag = nr.Windows.Controls.TristateStatusFlag.TristateFlag.Yellow;
            Server.Start();
            visualServerStatus.Flag = nr.Windows.Controls.TristateStatusFlag.TristateFlag.Green;
            btnServerStop.Enabled = true;
        }

        private void btnServerStop_Click(object sender, EventArgs e)
        {
            DialogResult answer =
                MessageBox.Show(this,"Confermando la chiusura del server, verranno disconnessi tutti i client dalla partita!\n\rSei sicuro di voler fermare il server?",
                    "[nr.Tombola] Server di Gioco", MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2);
            if (answer == System.Windows.Forms.DialogResult.Yes)
            {
                btnServerStop.Enabled = false;
                visualServerStatus.Flag = nr.Windows.Controls.TristateStatusFlag.TristateFlag.Yellow;
                Server.Stop();
                visualServerStatus.Flag = nr.Windows.Controls.TristateStatusFlag.TristateFlag.Red;
                btnServerStart.Enabled = true;
            }
        }

        private void btnExtract_Click(object sender, EventArgs e)
        {
            btnExtract.Enabled = false;
            int number = Game.Extract();
            if (number == 0)
                EndOfGame();
            else
            {
                AcceptButton = btnExtract;
                LastExtract = DateTime.Now;
                Server.Extract(number);
                lblLastNumber.Text = number.ToString();
                lbNumbers.Items.Insert(0, number.ToString());
                lblGameStatus.Text = string.Format("Estratti: {0}", lbNumbers.Items.Count);
            }
        }

        private void miGameExit_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (Game.Running)
            {
                MessageBox.Show(this,"Prima di chiudere il programma occorre terminare la partita in corso!", "[nr.Tombola] Server di Gioco", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
                e.Cancel = true;
            }
            else
            {
                if (Server.Running) Server.Stop();
            }
        }

        private void txtManualNumber_KeyPress(object sender, KeyPressEventArgs e)
        {
            e.Handled = !(char.IsControl(e.KeyChar) || char.IsDigit(e.KeyChar));
        }

        private void btnManuaExtract_Click(object sender, EventArgs e)
        {
            int number = int.Parse(txtManualNumber.Text);
            if (Game.Pull(number))
            {
                AcceptButton = btnManuaExtract;
                LastExtract = DateTime.Now;
                Server.Extract(number);
                lblLastNumber.Text = number.ToString();
                lbNumbers.Items.Insert(0, number.ToString());
                lblGameStatus.Text = string.Format("Estratti: {0}", lbNumbers.Items.Count);
                txtManualNumber.Text = string.Empty;
                txtManualNumber.Focus();
            }
        }

        private void txtManualNumber_TextChanged(object sender, EventArgs e)
        {
            btnManuaExtract.Enabled = txtManualNumber.Text.Length > 0;
        }

        private void txtManualNumber_Enter(object sender, EventArgs e)
        {
            AcceptButton = btnManuaExtract;
        }
    }
}
